package com.tedu.egmvcboot.exeception;

import com.tedu.egmvcboot.result.JsonResult;
import com.tedu.egmvcboot.result.Status;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * 全局异常处理器
 * 1:要在当前类上添加注解:@ControllerAdvice
 * 2:每一个方法用于处理一个特定的异常(相当于catch)
 *   并且方法上要使用注解:@ExceptionHandler
 *
 * 这样一来一旦一个Controller处理某个请求的方法在处理过程中抛出了
 * 一个异常时，SpringMVC框架就会使用当前类的对应方法来处理该异常
 * 即:抛出的异常与当前类某个方法参数异常类型匹配的方法
 */
//@ControllerAdvice
//使用该注解就无需在每个方法上使用@ResponseBody注解了，与RestController道理一致
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /*@ExceptionHandler
    public JsonResult doHandleIllegalArgumentException(IllegalArgumentException e){
        System.out.println("参数不合法");
        return new JsonResult(Status.VALIDATED_ERROR, e.getMessage());
    }*/
    /*
        相当于catch(RuntimeException e)
        由于Controller处理用户请求的方法抛出了异常，那么就意味着该方法没有机会将处理的结果
        回复给客户端了，而是将异常的处理放在当前方法来进行，因此该方法处理完异常后的返回值就是
        给客户端回复的内容了。
     */
//    @ExceptionHandler
//    @ResponseBody
//    public JsonResult doHandleRuntimeException(RuntimeException e) {
//        return new JsonResult(Status.OPERATION_ERROR,e.getMessage());
//    }

    /**
     * 当验证框架在验证浏览器发送过来的数据时没有验证通过，此时会抛出下面的异常
     * 异常自身提供的message信息比较繁多，我们通常只需要将基本的原因返回即可
     * 比如可以使用:e.getFieldError().getDefaultMessage()
     */
    @ExceptionHandler
    public JsonResult doHandleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        String message = e.getFieldError().getDefaultMessage();
        log.warn(message,e);//当验证框架不通过时，可以记录警告
        return new JsonResult(Status.VALIDATED_ERROR,message);
    }
    @ExceptionHandler
    public JsonResult doHandleConstraintViolationException(ConstraintViolationException e){
        String message = e.getMessage();//findById.id: 微博ID必须在1-9999之间
        message = message.substring(message.indexOf(":")+1).trim();
        log.warn(message,e);
        return new JsonResult(Status.VALIDATED_ERROR,message);
    }

    //通常我们可以捕获一个范围较大的异常，避免因为出现一些为指定的异常导致没有响应的情况
    /*@ExceptionHandler
    public JsonResult doHandleException(Exception e) {
        log.error(e.getMessage(),e);
        return new JsonResult(Status.UNKNOWN_ERROR);
    }*/
}
